﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows.Input;
using Trackr.Core.Entities;
using Trackr.GUI.Extensions;
using Trackr.Dispatcher.Extensions;
namespace Trackr.GUI.Views
{
	public class MainWindowViewModel : INotifyPropertyChanged
	{
        public Core.Entities.TimeItem CurrentTimeItem
        {
            get { return _currentTimeItem; }
            set
            {
                PreviousTimeItem = _currentTimeItem;
                _currentTimeItem = value;
            }
        }

	    public Core.Entities.TimeItem PreviousTimeItem { get; private set; }

		private int _currentWeek;
		private int _currentYear;
		private int _maxWeekNr;
		private Core.Entities.StopWatch _stopWatch;
		private WeekView _currentWeekView;
		public event EventHandler TaskSubmitted;
		public MainWindowViewModel()
		{
			//Trackr.Core.GenerateDummyData.Generate(2, 7, DateTime.Now.AddDays(-21), DateTime.Now);
			//Trackr.Core.Trackr.Instance.ClearData();
			CurrentTimeItem = Core.Trackr.Instance.GetLatestTimeItem();
			if (CurrentTimeItem != null)
				_maxWeekNr = CurrentTimeItem.StartDate.GetWeek();
			_currentWeek = DateTime.Now.GetWeek();
			_currentYear = DateTime.Now.Year;
			_stopWatch = new Core.Entities.StopWatch();
			_stopWatch.Start();
			CurrentWeekView = GetWeekView(_currentWeek, _currentYear);
		}

		#region commands

		private ICommand _submitTaskCommand;
		public ICommand SubmitTaskCommand
		{
			get
			{
				if (_submitTaskCommand != null)
					return _submitTaskCommand;

				return _submitTaskCommand = new Trackr.GUI.ViewModels.RelayCommand((obj) =>
				{
					string task = obj as string;
					if (String.IsNullOrWhiteSpace(task))
						return;

					CreateNewTask(task);
				});
			}
		}

	    public void CreateNewTask(string task)
	    {
	        if (CurrentTimeItem != null)
	        {
	            if (CurrentTimeItem.Task == task)
	            {
	                if (TaskSubmitted != null)
	                    TaskSubmitted(CurrentTimeItem, EventArgs.Empty);
	            }

	            _stopWatch.Stop();
	            CurrentTimeItem.AddDuration(_stopWatch.Duration);
	            Core.Trackr.Instance.Update(CurrentTimeItem.Id, CurrentTimeItem);
	        }
	        Core.Trackr.Instance.AddNew(task);
	        CurrentTimeItem = Core.Trackr.Instance.GetLatestTimeItem();

	        //notify subscribers
	        new Publishers.TimeItemAdded(CurrentTimeItem.Id).Publish();
	        _stopWatch.Start();

	        if (TaskSubmitted != null)
	            TaskSubmitted(CurrentTimeItem, EventArgs.Empty);
	        
            CurrentWeekView = GetWeekView(_currentWeek, _currentYear);
	    }

	    private ICommand _showPreviousWeek;
		public ICommand ShowPreviousWeek
		{
			get
			{
				if (_showPreviousWeek != null)
					return _showPreviousWeek;

				return _showPreviousWeek = new Trackr.GUI.ViewModels.RelayCommand((obj) =>
				{
					GetPreviousWeek();

				});
			}
		}

		private void GetPreviousWeek()
		{
			int currentWeek = CurrentWeekNr;
			if (currentWeek == 1)
			{
				CurrentWeekNr = 52;
				_currentYear--;
			}
			else
			{
				CurrentWeekNr--;
			}
			//CurrentWeekNr = CurrentWeekNr == 1 ? 52 : CurrentWeekNr -= 1;
			CurrentWeekView = GetWeekView(_currentWeek, _currentYear);
		}
		private ICommand _showNextWeek;
		public ICommand ShowNextWeek
		{
			get
			{
				if (_showNextWeek != null)
					return _showNextWeek;

				return _showNextWeek = new Trackr.GUI.ViewModels.RelayCommand((obj) =>
				{
					GetNextWeek();
				});
			}
		}

		private void GetNextWeek()
		{
			if (_currentWeek == _maxWeekNr)
				return;
			int currentWeek = CurrentWeekNr;
			if (currentWeek == 52)
			{
				CurrentWeekNr = 1;
				_currentYear++;
			}
			else
			{
				CurrentWeekNr++;
			}
			CurrentWeekView = GetWeekView(CurrentWeekNr, _currentYear);
		}

		private ICommand _leftKeyDownCommand;
		public ICommand LeftKeyDownCommand
		{
			get
			{
				if (_leftKeyDownCommand != null)
					return _leftKeyDownCommand;

				return _leftKeyDownCommand = new Trackr.GUI.ViewModels.RelayCommand((obj) =>
				{
					GetPreviousWeek();
				});
			}
		}
		private ICommand _rightKeyDownCommand;
	    private TimeItem _currentTimeItem;

	    public ICommand RightKeyDownCommand
		{
			get
			{
				if (_rightKeyDownCommand != null)
					return _rightKeyDownCommand;

				return _rightKeyDownCommand = new Trackr.GUI.ViewModels.RelayCommand((obj) =>
				{
					GetNextWeek();
				});
			}
		}
		public event PropertyChangedEventHandler PropertyChanged;
		private void OnPropertyChanged(string propertyName)
		{
			if (PropertyChanged != null)
			{
				PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
			}
		}
		#endregion commands

		public string PlaceholderText
		{
			get { return CurrentTimeItem != null ? CurrentTimeItem.Task : "What are you doing?"; }
			set { }
		}
		public string CurrentWeekNrText
		{
			get { return string.Format("week {0}", CurrentWeekNr); }
		}
		public int CurrentWeekNr
		{
			get { return _currentWeek; }
			set
			{
				_currentWeek = value;
				OnPropertyChanged("CurrentWeekNr");
				OnPropertyChanged("CurrentWeekNrText");
			}
		}
		public Views.WeekView CurrentWeekView
		{
			get { return _currentWeekView; }
			set
			{
				_currentWeekView = value;
				OnPropertyChanged("CurrentWeekView");
			}
		}

		#region private
		private Views.WeekView GetWeekView(int weekNr, int year)
		{
			var startDate = weekNr.GetWeekStartDate(year);
			//startDate = DateTime.Now.AddDays(-2);
			var timeItems = Trackr.Core.Trackr.Instance.GetTimeItems(startDate, startDate.AddDays(6));
			var weekView = new Views.WeekView();
			weekView.stackPanelDayItems.Children.Clear();
			//get the days. group them by day date
			var days = timeItems.GroupBy(t => t.StartDate.Date).OrderByDescending(ti => ti.Key).ToDictionary(i => i.Key, i => i.ToList());

			foreach (var dayDate in days.Keys)
			{
				var dayTimeItmes = days[dayDate].OrderByDescending(ti => ti.StartDate);
				var groupedDayItems = dayTimeItmes.GroupBy(k => k.Task).ToDictionary(k => k.Key, k => k.Sum(i => i.GetDuration().TotalSeconds));
                var totalSeconds = dayTimeItmes.Sum(time => time.RunningSeconds);
                var totalDayTime = TimeSpan.FromSeconds(totalSeconds);
				var timeItemViews = groupedDayItems.Select(ti => new Views.TimeItemView(ti.Key, TimeSpan.FromSeconds(ti.Value)));
				var dayView = new Views.DayView(dayDate, totalDayTime);
				dayView.stackPanelTimeItems.Children.Clear();
				foreach (var tiView in timeItemViews)
				{
					dayView.stackPanelTimeItems.Children.Add(tiView);
				}
				weekView.stackPanelDayItems.Children.Add(dayView);
			}
			weekView.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
			return weekView;
		}

	    #endregion private

		/// <summary>
		/// Will stop/end the current time item
		/// <para>Will add the duration of the current stopwatch to the current time item</para>
		/// </summary>
		public void StopCurrent()
		{
			if (CurrentTimeItem == null)
				return;
			_stopWatch.Stop();
			CurrentTimeItem.AddDuration(_stopWatch.Duration);
			Trackr.Core.Trackr.Instance.Update(CurrentTimeItem.Id, CurrentTimeItem);
			_stopWatch.Clear();
		}
	}
}
